package com.ag.oa.core.service.impl;

import com.ag.oa.constant.CommonConstant;
import com.ag.oa.core.dao.IProjectDao;
import com.ag.oa.core.dao.IUserDao;
import com.ag.oa.core.entity.dto.UserScoreDTO;
import com.ag.oa.core.entity.vo.SkillVO;
import com.ag.oa.core.entity.vo.UserVO;
import com.ag.oa.core.service.UserService;
import com.ag.oa.redis.RedisConstant;
import com.ag.oa.redis.RedisUtils;
import com.ag.oa.util.*;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service("userServiceImpl")
public class UserServiceImpl implements UserService {

    @Autowired
    private IUserDao userDao;

    @Autowired
    private IProjectDao projectDao;

    @Autowired
    private RedisUtils redisUtils;

    private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

    private static final String APPID = "";
    private static final String SECRET = "";

    @Override
    public void saveWxUserAuthRegister(String code, JSONObject res) {

        String url = "https://api.weixin.qq.com/sns/jscode2session?appid="+ APPID +"&secret="+ SECRET
                +"&js_code="+ code +"&grant_type=authorization_code";

        // 调用 auth.code2Session 接口，换取 用户唯一标识 OpenID 和 redis保存会话密钥 session_key
        String resStr = NetClientUtil.sendGet(url);
//        logger.info("--code2Session 结果: "+ resStr);

        boolean success = false;
        JSONObject result = JSONObject.parseObject(resStr);
        if (result.containsKey("openid")) {
            success = true;

            String openId = result.getString("openid");
            String sessionKey = result.getString("session_key");

            UserVO user = userDao.getById(openId);
            if (user == null) {
                // 为空则new一个，避免下面空指针报错。这一步不必新增用户信息。
                user = new UserVO();

                // 没有找到openId数据，表示属于小程序的新用户
                res.put("isNewWXUser", true);
            } else {
                res.put("isNewWXUser", false);
                logger.info("--code2Session 结果: "+ resStr);
            }

            // 进入小程序，刷新sessionKey（微信内部存在过期逻辑，所以需要刷新），保存24小时
            redisUtils.set(RedisConstant.USER_SESSION_KEY + openId, sessionKey, 60*60*24);

            // 返回值openId，其中sessionKey采用redis保存，避免触发平台安全问题
            res.put("openId", openId);

            // 增加用户头像，聊天使用 add by wjc 2022/03/08
            res.put("userId", user.getId()==null? -1 : user.getId());
            res.put("username", user.getUsername()==null? "": user.getUsername());
            res.put("avatarUrl", StringUtils.isBlank(user.getAvatarUrl()) ? CommonConstant.DEFAULT_AVATAR : user.getAvatarUrl());
            res.put("score", user.getScore()==null? 0: user.getScore());

            // 增加手机号，完善用户使用 add by wjc 2022/11/23
            res.put("phone", user.getPhone());
        }
        res.put("success", success);
    }

    @Override
    public void saveAuthRegisterUserInfo(String openId, String userInfoStr, JSONObject res) {

        JSONObject userInfo = JSONObject.parseObject(userInfoStr);
        String avatarUrl = StringUtils.isBlank(userInfo.getString("avatarUrl")) ? CommonConstant.DEFAULT_AVATAR : userInfo.getString("avatarUrl");

        UserVO user = userDao.getById(openId);
        if (user==null) {
            user = new UserVO();
            user.setOpenId(openId);
            user.setUsername(userInfo.getString("nickName"));
            user.setAvatarUrl(avatarUrl);
            user.setGender(userInfo.getInteger("gender"));
            user.setCountry(userInfo.getString("country"));
            user.setProvince(userInfo.getString("province"));
            user.setCity(userInfo.getString("city"));
            user.setPhone("");
            user.setVip(0);
            userDao.saveNewWxRegisterUser(user);
        }
        res.put("userInfo", user);
    }

    @Override
    public void saveCompleteUser(String openId, String username, String phone, String smsCode, JSONObject res) {
        UserVO user = userDao.getById(openId);
        if (user == null) {
            // 老用户，后台查询用户数据，不应该为空
            res.put("resCode", 201);
            res.put("message", "数据异常");
            return;
        }

        user.setOpenId(openId);

        // 完善，昵称部分
        String oldUsername = user.getUsername();
        if (!BaseUtils.checkUsername(oldUsername)) {
            if (!BaseUtils.checkUsername(username)) {
                res.put("resCode", 201);
                res.put("message", "昵称不符合要求");
                return;
            }

            if (userDao.getCountByUsername(username) > 0) {
                res.put("resCode", 201);
                res.put("message", "该昵称已存在");
                return;
            }

            user.setUsername(username);
        }

        // 完善，手机号部分
        String oldPhone = user.getPhone();
        if (StringUtils.isBlank(oldPhone)) {
            if (!BaseUtils.isChinaCellPhoneNumber(phone)) {
                res.put("resCode", 201);
                res.put("message", "手机号无效");
                return;
            }
            if (!BaseUtils.checkSmsCode(smsCode)) {
                res.put("resCode", 201);
                res.put("message", "短信验证码无效");
                return;
            }

            // 校验注册的 smsCode 是否正确
            String serverCode = (String) redisUtils.get(RedisConstant.SMS_WX_COMPLETE_USER + phone);
            if (serverCode == null) {
                res.put("resCode", 201);
                res.put("message","短信验证码无效，请重新获取");
                return;
            }
            if (!serverCode.equals(smsCode)) {
                res.put("resCode", 201);
                res.put("message","短信验证码错误，请重新输入");
                return;
            } else {
                // 短信验证码，校验成功后，立即删除
                redisUtils.del(RedisConstant.SMS_WX_COMPLETE_USER + phone);
            }

            if (userDao.getCountByPhone(phone) > 0) {
                res.put("resCode", 201);
                res.put("message", "该手机号已绑定");
                return;
            }

            user.setPhone(phone);
        }

        userDao.updateUsernameOrPhone(user);
        res.put("userInfo", user);
    }

    @Override
    public void saveNewUser(String openId, String username, String phone, String smsCode, JSONObject res) {
        // 微信新用户，不应该有值
        UserVO user = userDao.getById(openId);
        if (user != null) {
            res.put("resCode", 201);
            res.put("message", "数据异常");
            return;
        }

        // 查询手机号，最多不超过1条数据
        int count = userDao.getCountByPhone(phone);
        if (count > 1) {
            res.put("resCode", 201);
            res.put("message", "数据异常");
            return;
        }

        // 只有全新的用户，才存在昵称的校验
        if(count == 0) {
            if (!BaseUtils.checkUsername(username)) {
                res.put("resCode", 201);
                res.put("message", "昵称不符合要求");
                return;
            }
            if (userDao.getCountByUsername(username) > 0) {
                res.put("resCode", 201);
                res.put("message", "该昵称已存在");
                return;
            }
        }

        if (!BaseUtils.isChinaCellPhoneNumber(phone)) {
            res.put("resCode", 201);
            res.put("message", "手机号无效");
            return;
        }
        if (!BaseUtils.checkSmsCode(smsCode)) {
            res.put("resCode", 201);
            res.put("message", "短信验证码无效");
            return;
        }

        // 校验注册的 smsCode 是否正确
        String serverCode = (String) redisUtils.get(RedisConstant.SMS_WX_NEW_USER + phone);
        if (serverCode == null) {
            res.put("resCode", 201);
            res.put("message","短信验证码无效，请重新获取");
            return;
        }
        if (!serverCode.equals(smsCode)) {
            res.put("resCode", 201);
            res.put("message","短信验证码错误，请重新输入");
            return;
        } else {
            // 短信验证码，校验成功后，立即删除
            redisUtils.del(RedisConstant.SMS_WX_NEW_USER + phone);
        }


        // 全部验证通过之后
        if (count == 0){
            // 不存在，则新增用户
            user = new UserVO();
            user.setOpenId(openId);
            user.setUsername(username);
            user.setAvatarUrl(CommonConstant.DEFAULT_AVATAR);
            user.setGender(0);
            user.setCountry("");
            user.setProvince("");
            user.setCity("");
            user.setPhone(phone);
            user.setVip(0);
            userDao.saveNewWxRegisterUser(user);
        }else if(count == 1){
            // 存在，则补充微信的open_id
            userDao.updateOpenIdByPhone(openId, phone);
        }

        // 查询最新的用户信息，返回
        res.put("userInfo", userDao.getById(openId));
    }

    @Override
    public void updateAuthUserInfo(String openId, String encryptedStr, String ivStr, String sessionKey
            , String rawDataStr, JSONObject res) {

        String phoneNumber = "";
        String decryptStr = WechatUtil.wxDecrypt(encryptedStr, sessionKey, ivStr);
        if (CustomUtil.strNotEmpty(decryptStr)) {
            JSONObject result = JSONObject.parseObject(decryptStr);
            phoneNumber = result.getString("phoneNumber");  // 国外手机号会有区号
        }

        // 基本信息
        JSONObject userInfo = JSONObject.parseObject(rawDataStr);
        if (userInfo==null) {
            return;
        }

        String username = userInfo.getString("username").trim();

        UserVO user = userDao.getById(openId);
        if (!CustomUtil.strNotEmpty(user.getUsername())) {  // 为空则设置名称
            user.setUsername(username);
        }
        user.setGender(userInfo.getInteger("gender"));
        user.setAvatarUrl(userInfo.getString("avatarUrl"));
        user.setPhone(phoneNumber);

        if (!CustomUtil.strNotEmpty(user.getCountry())) {
            user.setCountry(userInfo.getString("country"));
            user.setProvince(userInfo.getString("province"));
            user.setCity(userInfo.getString("city"));
        }

        logger.info("userInfo: "+ userInfo);
        userDao.updateAuthUser(user);
        res.put("username", username);
    }

    @Override
    public UserVO getUserInfoById(Integer id, String openId) {

        Object primaryKey = null;
        if (id!=null) {
            primaryKey = id;
        } else if (openId!=null) {
            primaryKey = openId;
        }

        UserVO user = userDao.getById(primaryKey);
        if (user!=null) {
            if (user.getRefereeUserId()!=null) { // 推荐人
                UserVO refereeUser = userDao.getById(user.getRefereeUserId());
                user.setReferee(refereeUser.getUsername());
            }

            // 默认用户头像
            if(StringUtils.isBlank(user.getAvatarUrl())) {
                user.setAvatarUrl(CommonConstant.DEFAULT_AVATAR);
            }
        }
        return user;
    }

    @Override
    public List<UserVO> getForPageList(Integer id, String username, Integer page, Integer pageSize) {

        if (page==null) {
            page = 0;
        }
        if (pageSize==null) {
            pageSize = 14;
        }

        if (!CustomUtil.strNotEmpty(username)) {
            username = null;
        }
        return userDao.getUserPageList(id, username, page * pageSize, pageSize);
    }

    /**
     * 修改用户信息
     * @param colType 0: 昵称, 1: 兴趣爱好, 2: 教育经历, 3: 工作经历, 4: 性别, 5: 学历, 6: 地区,
     *                7: 推荐人, 8: 姓名, 9: 手机号, 10: 出生年份
     */
    @Override
    public void updateModifyUserInfo(Integer userId, String valueStr, Integer colType, JSONObject res) {

        int code = 200;

        // 是否修改昵称
        if (colType==0) {
            int count = userDao.getCountByUsername(valueStr); // 是否存在昵称相同用户
            if (count==0) {
                userDao.updateUserByColumnType(userId, valueStr, colType);
            } else {
                code = 201;
            }
        } else if (colType==6) {
            String[] regionArr = valueStr.split("·");
            userDao.updateUserRegion(userId, regionArr[0], regionArr[1], regionArr[2]);
        } else {
            userDao.updateUserByColumnType(userId, valueStr, colType);
        }
        res.put("resCode", code);
    }

    @Override
    public List<UserVO> queryUsersDataByUsername(Integer userId, String username) {

        List<UserVO> list = new ArrayList<>();
        if (CustomUtil.strNotEmpty(username)) {
            list = userDao.getUsersDataByUsername(userId, username);
        }
        return list;
    }

    @Override
    public int saveUpdateRefereeUser(Integer userId, Integer refereeUserId) {

        UserVO user = userDao.getById(userId);
        UserVO refereeUser = userDao.getById(refereeUserId);

        int resCode = 201;

        // 推荐人，要做 注册时间判断。不能是注册时间晚的人 成我的推荐人
        if (user!=null && refereeUser!=null) {
            // 获取注册时间
            int myRegisterDate = Integer.parseInt(user.getCreated().replace("-", ""));
            int refereeRegisterDate = Integer.parseInt(refereeUser.getCreated().replace("-", ""));
            if (myRegisterDate > refereeRegisterDate) {
                resCode = 200;
                userDao.updateMyRefereeUser(userId, refereeUserId);
            }
        }
        return resCode;
    }

    @Override
    public void updateUserVipLevel(Integer userId, Integer vipLevel) {

        userDao.updateVipById(userId, vipLevel);
    }

    @Override
    public List<SkillVO> getUserWorkSkillList(Integer id) {

        return userDao.getWorkSkillListById(id);
    }

    @Override
    public boolean getUserHasAuthAddTask(Integer userId, Integer projectId) {

        boolean result = false;
        if (projectId==null) {
            UserVO userVO = userDao.getById(userId);
            if (userVO!=null && userVO.getVip()!=0) {
                result = true;
            }
        } else {
            Integer count = projectDao.getProjectManagerFlag(projectId, userId);
            if (count!=0) {
                result = true;
            }
        }
        return result;
    }

    @Override
    public List<Map<String, Object>> getUserScoreRecordList(Integer userId, Integer page, Integer pageSize) {

        if (page==null) {
            page = 0;
        }
        if (pageSize==null) {
            pageSize = 16;
        }
        return userDao.getScoreRecordList(userId, page * pageSize, pageSize);
    }

    @Override
    public boolean doUserOutScore(Integer userId, Integer transactionScore, String updated, Integer createdBy,
                                Integer sourceType, String additionalJson, String description) {
        // 如果交易积分为0，无需更新与记录，直接返回成功
        if(transactionScore == 0){
            return true;
        }

        // 获取用户当前积分
        UserVO user = userDao.getById(userId);
        Integer userNowScore = user.getScore();

        // 扣除积分
        Long updatedLong = DateUtils.stringToDate(updated, "yyyy-MM-dd HH:mm:ss").getTime()/1000;
        int row = userDao.updateUserOutScore(userId, transactionScore, updatedLong, userNowScore);
        if (row == 1) {
            // 支出积分成功，记录积分收支明细表
            UserScoreDTO scoreDTO = new UserScoreDTO();
            scoreDTO.setUserId(userId);
            scoreDTO.setSourceType(sourceType);
            scoreDTO.setPaymentType("out");
            scoreDTO.setTransactionScore(-transactionScore); // 支出的交易积分，显示为负数形式（便于对账）
            scoreDTO.setBeforeScore(userNowScore);
            scoreDTO.setAfterScore(userNowScore - transactionScore);
            scoreDTO.setCreatedBy(createdBy);
            scoreDTO.setCreated(updated);
            scoreDTO.setCreatedDate(updated.substring(0,10));
            scoreDTO.setAdditionalJson(additionalJson);
            scoreDTO.setDescription(description);
            userDao.insertUserScore(scoreDTO);
            return true;
        } else {
            // 支出积分失败，返回 false 状态（建议提示：用户积分异常，请稍后重试）
            return false;
        }
    }

    @Override
    public boolean doUserInScore(Integer userId, Integer transactionScore, String updated, Integer createdBy,
                               Integer sourceType, String additionalJson, String description) {
        if(transactionScore == 0){
            return true;
        }
        boolean inFlag = false;

        for (int i = 0; i < 3; i++) {
            // 获取用户当前积分
            UserVO user = userDao.getById(userId);
            Integer userNowScore = user.getScore();
            // 增加积分
            Long updatedLong = DateUtils.stringToDate(updated, "yyyy-MM-dd HH:mm:ss").getTime()/1000;
            int row = userDao.updateUserInScore(userId, transactionScore, updatedLong, userNowScore);
            if (row == 1) {
                // 支出积分成功，记录积分收支明细表
                UserScoreDTO scoreDTO = new UserScoreDTO();
                scoreDTO.setUserId(userId);
                scoreDTO.setSourceType(sourceType);
                scoreDTO.setPaymentType("in");
                scoreDTO.setTransactionScore(transactionScore);
                scoreDTO.setBeforeScore(userNowScore);
                scoreDTO.setAfterScore(userNowScore + transactionScore);
                scoreDTO.setCreatedBy(createdBy);
                scoreDTO.setCreated(updated);
                scoreDTO.setCreatedDate(updated.substring(0,10));
                scoreDTO.setAdditionalJson(additionalJson);
                scoreDTO.setDescription(description);
                userDao.insertUserScore(scoreDTO);

                inFlag = true;
                break;
            } else {
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        return inFlag;
    }

    @Override
    public int getCountByPhone(String phone) {
        return userDao.getCountByPhone(phone);
    }

    @Override
    public void updatePublicStatusByUserId(Integer userId, Integer publicStatus) {
        userDao.updatePublicStatusByUserId(userId, publicStatus);
    }


}
